home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / rayshade / libray / libobj / bounds.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  249 lines

  1. /*
  2.  * bounds.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: bounds.c,v 1.1 1994/05/13 00:14:59 millard Exp millard $
  17.  *
  18.  * $Log: bounds.c,v $
  19.  * Revision 1.1  1994/05/13  00:14:59  millard
  20.  * Initial revision
  21.  *
  22.  * Revision 4.0.1.2  91/10/05  18:17:29  cek
  23.  * patch1: Faster box transform, a la Jim Arvo.
  24.  * 
  25.  * Revision 4.0.1.1  1991/09/29  15:42:05  cek
  26.  * patch1: Justified floating point compare...
  27.  *
  28.  * Revision 4.0  91/07/17  14:36:21  kolb
  29.  * Initial version.
  30.  * 
  31.  */
  32. #include "geom.h"
  33.  
  34. /*
  35.  * Check for intersection between bounding box and the given ray.
  36.  * If there is an intersection between mindist and *maxdist along
  37.  * the ray, *maxdist is replaced with the distance to the point of
  38.  * intersection, and TRUE is returned.  Otherwise, FALSE is returned.
  39.  *
  40.  * If this routine is used to check for intersection with a volume
  41.  * rather than a "hollow" box, one should first determine if
  42.  * (ray->pos + mindist * ray->dir) is inside the bounding volume, and
  43.  * call BoundsIntersect() only if it is not.
  44.  */
  45. int
  46. BoundsIntersect(ray, bounds, mindist, maxdist)
  47. Ray *ray;
  48. Float bounds[2][3], mindist, *maxdist;
  49. {
  50.     Float t, tmin, tmax;
  51.     Float dir, pos;
  52.  
  53.     tmax = *maxdist;
  54.     tmin = mindist;
  55.  
  56.     dir = ray->dir.x;
  57.     pos = ray->pos.x;
  58.  
  59.     if (dir < 0) {
  60.         t = (bounds[LOW][X] - pos) / dir;
  61.         if (t < tmin)
  62.             return FALSE;
  63.         if (t <= tmax)
  64.             tmax = t;
  65.         t = (bounds[HIGH][X] - pos) / dir;
  66.         if (t >= tmin) {
  67.             if (t > tmax)
  68.                 return FALSE;
  69.             tmin = t;
  70.         }
  71.     } else if (dir > 0.) {
  72.         t = (bounds[HIGH][X] - pos) / dir;
  73.         if (t < tmin)
  74.             return FALSE;
  75.         if (t <= tmax)
  76.             tmax = t;
  77.         t = (bounds[LOW][X] - pos) / dir;
  78.         if (t >= tmin) {
  79.             if (t > tmax)
  80.                 return FALSE;
  81.             tmin = t;
  82.         }
  83.     } else if (pos < bounds[LOW][X] || pos > bounds[HIGH][X])
  84.         return FALSE;
  85.  
  86.     dir = ray->dir.y;
  87.     pos = ray->pos.y;
  88.  
  89.     if (dir < 0) {
  90.         t = (bounds[LOW][Y] - pos) / dir;
  91.         if (t < tmin)
  92.             return FALSE;
  93.         if (t <= tmax)
  94.             tmax = t;
  95.         t = (bounds[HIGH][Y] - pos) / dir;
  96.         if (t >= tmin) {
  97.             if (t > tmax)
  98.                 return FALSE;
  99.             tmin = t;
  100.         }
  101.     } else if (dir > 0.) {
  102.         t = (bounds[HIGH][Y] - pos) / dir;
  103.         if (t < tmin)
  104.             return FALSE;
  105.         if (t <= tmax)
  106.             tmax = t;
  107.         t = (bounds[LOW][Y] - pos) / dir;
  108.         if (t >= tmin) {
  109.             if (t > tmax)
  110.                 return FALSE;
  111.             tmin = t;
  112.         }
  113.     } else if (pos < bounds[LOW][Y] || pos > bounds[HIGH][Y])
  114.         return FALSE;
  115.  
  116.     dir = ray->dir.z;
  117.     pos = ray->pos.z;
  118.  
  119.     if (dir < 0) {
  120.         t = (bounds[LOW][Z] - pos) / dir;
  121.         if (t < tmin)
  122.             return FALSE;
  123.         if (t <= tmax)
  124.             tmax = t;
  125.         t = (bounds[HIGH][Z] - pos) / dir;
  126.         if (t >= tmin) {
  127.             if (t > tmax)
  128.                 return FALSE;
  129.             tmin = t;
  130.         }
  131.     } else if (dir > 0.) {
  132.         t = (bounds[HIGH][Z] - pos) / dir;
  133.         if (t < tmin)
  134.             return FALSE;
  135.         if (t <= tmax)
  136.             tmax = t;
  137.         t = (bounds[LOW][Z] - pos) / dir;
  138.         if (t >= tmin) {
  139.             if (t > tmax)
  140.                 return FALSE;
  141.             tmin = t;
  142.         }
  143.     } else if (pos < bounds[LOW][Z] || pos > bounds[HIGH][Z])
  144.         return FALSE;
  145.  
  146.     /*
  147.      * If tmin == mindist, then there was no "near"
  148.      * intersection farther than EPSILON away.
  149.      */
  150.     if (tmin == mindist) {
  151.         if (tmax < *maxdist) {
  152.             *maxdist = tmax;
  153.             return TRUE;
  154.         }
  155.     } else {
  156.         if (tmin < *maxdist) {
  157.             *maxdist = tmin;
  158.             return TRUE;
  159.         }
  160.     }
  161.     return FALSE;    /* hit, but not closer than maxdist */
  162. }
  163.  
  164. /*
  165.  * Transform an object's bounding box by the given transformation
  166.  * matrix.
  167.  */
  168. void
  169. BoundsTransform(trans, objbounds)
  170. RSMatrix *trans;
  171. Float objbounds[2][3];
  172. {
  173.     Float bounds[2][3], a, b;
  174.     int i, j;
  175.  
  176.     /*
  177.      * Can't (and shouldn't) do anything with unbounded objects.
  178.      */
  179.     if (objbounds[LOW][X] > objbounds[HIGH][X])
  180.         return;
  181.  
  182.     bounds[LOW][X] = bounds[HIGH][X] = trans->translate.x;
  183.     bounds[LOW][Y] = bounds[HIGH][Y] = trans->translate.y;
  184.     bounds[LOW][Z] = bounds[HIGH][Z] = trans->translate.z;
  185.  
  186.     for (i = 0; i < 3; i++) {
  187.         for (j = 0; j < 3; j++) {
  188.             a = trans->matrix[j][i] * objbounds[LOW][j];
  189.             b = trans->matrix[j][i] * objbounds[HIGH][j];
  190.             if (a < b) {
  191.                 bounds[LOW][i] += a;
  192.                 bounds[HIGH][i] += b;
  193.             } else {
  194.                 bounds[LOW][i] += b;
  195.                 bounds[HIGH][i] += a;
  196.             }
  197.         }
  198.     }
  199.     BoundsCopy(bounds, objbounds);
  200. }
  201.  
  202. void
  203. BoundsInit(bounds)
  204. Float bounds[2][3];
  205. {
  206.     bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = FAR_AWAY;
  207.     bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -FAR_AWAY;
  208. }
  209.  
  210. void
  211. BoundsCopy(from, into)
  212. Float into[2][3], from[2][3];
  213. {
  214.     into[LOW][X] = from[LOW][X];
  215.     into[LOW][Y] = from[LOW][Y];
  216.     into[LOW][Z] = from[LOW][Z];
  217.     into[HIGH][X] = from[HIGH][X];
  218.     into[HIGH][Y] = from[HIGH][Y];
  219.     into[HIGH][Z] = from[HIGH][Z];
  220. }
  221.  
  222. #define SetIfLess(a, b)        (a = ((a) < (b) ? (a) : (b)))
  223. #define SetIfGreater(a, b)    (a = ((a) > (b) ? (a) : (b)))
  224.  
  225. /*
  226.  * Find bounding box of the union of two bounding boxes.
  227.  */
  228. void
  229. BoundsEnlarge(old, new)
  230. Float old[2][3], new[2][3];
  231. {
  232.     SetIfLess(old[LOW][X], new[LOW][X]);
  233.     SetIfLess(old[LOW][Y], new[LOW][Y]);
  234.     SetIfLess(old[LOW][Z], new[LOW][Z]);
  235.     SetIfGreater(old[HIGH][X], new[HIGH][X]);
  236.     SetIfGreater(old[HIGH][Y], new[HIGH][Y]);
  237.     SetIfGreater(old[HIGH][Z], new[HIGH][Z]);
  238. }
  239.  
  240. void
  241. BoundsPrint(box, fp)
  242. Float box[2][3];
  243. FILE *fp;
  244. {
  245.     fprintf(fp,"\tX: %f to %f\n",box[LOW][X], box[HIGH][X]);
  246.     fprintf(fp,"\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]);
  247.     fprintf(fp,"\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]);
  248. }
  249.